--extend UserData

local SpecType = import(".SpecType")
local Skill = import(".Skill")
local Rune = import(".Rune")
local Talent = import(".Talent")
local UserData = import(".UserData")

-- 初始化技能相关的配置
function UserData:initSkillConf()
    self._specTypes = nil -- 职业专精信息
    self._talentDict = nil -- 本职业所有talent的dict
    self._talentsSpecDict = nil -- 本职业按specId分组的talent
    self._runesSpecDict = nil -- 我的专精符文数据列表dict
    self._runeDict = nil -- 所有rune的dict
    self._runePlaceDirtyDict = {} -- 符文位置数据变化，主要用来排序

    self:_initSpecTypes()
    self:_initAllTalents()
    self:_initRuneData()
end

------------------------- 专精 -----------------------
function UserData:_initSpecTypes()
    local specTypes = {}
    local confs = GD:getSpec_typeConfigByClass(UD:getClass())
    local curSpecId = self:getCurSpecTypeId()
    for i,conf in ipairs(confs) do
        local specId = tonumber(conf.ID)
        local specType = SpecType.new(specId, conf)
        specType:setActive(specId == curSpecId)
        specTypes[#specTypes + 1] = specType
    end
    self._specTypes = specTypes
end

function UserData:getSpecTypes()
    return self._specTypes
end

function UserData:getSpecType(specId)
    for i,specType in ipairs(self._specTypes) do
        if specType:getId() == specId then
            return specType
        end
    end
end

-- 当前专精id
function UserData:getCurSpecTypeId()
    return self.player.skillChooseID
end

-- 专精技能选择
function UserData:getSkillChoose(specId)
    specId = specId or self.player.skillChooseID
    local skillChoose=self.skillChooses[specId]
    return skillChoose
end

function UserData:getSkillChooses()
    return self.skillChooses
end

--激活专精后 需要处理当前天赋 批量处理
function UserData:onActiveSpecType(newTalents, oldTalents)
    --先移除 再添加
    if oldTalents then
        for k,v in ipairs(oldTalents) do
            local uid = v.uid
            local talent = self:getTalent(uid)
            talent:setActive(false)
            self.talents[uid]=nil
        end
    end

    if newTalents then
        for k,v in ipairs(newTalents) do
            local uid = v.uid
            local talent = self:getTalent(uid)
            talent:setActive(true)
            self.talents[uid]=talent
        end
    end

    -- 修改specType激活状态
    local curSpecId = self:getCurSpecTypeId()
    for i,specType in ipairs(self._specTypes) do
        specType:setActive(curSpecId == specType:getId())
    end

    local eventName="talent"
    local eventArgs={}
    self:calUserdataAttr() -- 属性数据过期，重算
    self:dispatchChange(eventName,unpack(eventArgs))
end

------------------------- 技能 -----------------------
function UserData:getSkills()
    return self.skills
end

function UserData:hasSkill(id)
    return self.skills[id]~=nil
end

function UserData:getSkillPoint()
    return self._coinWallets[85] or 0
end

function UserData:getSkill(skillId)
    return self.skills[skillId]
end

-- 一个组同时只有一个技能
function UserData:getSkillByTeam(team)
    for _,skill in pairs(self.skills) do
        if skill:getTeam() == team then
            return skill
        end
    end
end

-- 根据技能组获得当前激活的技能id
function UserData:getSkillIdByTeam(team)
    local skill = self:getSkillByTeam()
    if skill then
        return skill:getId()
    end
end

-- 获得专精可以替换的技能
function UserData:getSpecChangeSkills(specType)
    local skills = {}
    local skillTeams = specType:getChangeSkillTeams()
    for _,team in ipairs(skillTeams) do
        local skill = self:getSkillByTeam(team)
        if not skill then
            -- 没有技能创建该组等级为1的技能
            local firstConf = GD:getFirstSkillConfByTeam(team)
            if firstConf then
                skill = Skill.new()
                skill:read({uid=tonumber(firstConf.ID)})
            end
        end
        if skill then
            table.insert(skills, skill)
        end
    end
    return skills
end

-- 获得专精可以替换的技能
function UserData:getSpecChooseSkills(specType)
    -- 1. 从skillChoose里面取显示的技能（剔除通用技能）
    local specId = specType:getId()
    local generalSkillTeam = specType:getGeneralSkillTeam()
    local skillChoose = self:getSkillChoose(specId)
    local skillTeams = {0,0,0,0,0}
    if skillChoose then
        for i=1,5 do
            skillTeams[i] = skillChoose.teamIds[i]
        end

        -- 2. 使用神器技能组id（需要替换成正常技能组id）
        for i,info in ipairs(skillChoose.legendSkillInfo) do
            local index, legendSkillTeam = info.index + 1, info.legendSkillID
            if index > 0 and index <= 5 and legendSkillTeam > 0 then
                local teamId = GD:getLegendSkillTeam(legendSkillTeam)
                if teamId > 0 then
                    skillTeams[index] = teamId
                end
            end
        end
    end

    -- 3. 技能teamId为0的填充默认值
    local defSkillTeams = specType:getDefaultSkillTeams()
    for i,teamId in ipairs(skillTeams) do
        if teamId == 0 then
            skillTeams[i] = defSkillTeams[i]
        end
    end

    local skills = {}
    for _,team in ipairs(skillTeams) do
        local skill = self:getSkillByTeam(team)
        if not skill then
            -- 没有技能创建该组等级为1的技能
            local firstConf = GD:getFirstSkillConfByTeam(team)
            if firstConf then
                skill = Skill.new()
                skill:read({uid=tonumber(firstConf.ID)})
            end
        end
        if skill then
            table.insert(skills, skill)
        end
    end

    return skills
end

-- 获得专精的激活技能
function UserData:getSpecActiveSkills(specId)
    local skillChoose = self:getSkillChoose(specId)
    if not skillChoose then return {} end

    local skillTeams = skillChoose.teamIds
    local skills = {}
    for _,team in ipairs(skillTeams) do
        local skill = self:getSkillByTeam(team)
        if skill then
            table.insert(skills, skill)
        end
    end
    return skills
end

function UserData:hasSkillCanUpgrade()
    --TODO 判断成就解锁技能,目前表格字段是空的,待新成就设计后判断是否需要
    if self:getSkillPoint() <= 0 then
        return false
    end

    local ret = false
    local activeSkills = self:getSpecActiveSkills()
    for _,skill in pairs(activeSkills) do
        if skill:canUpgrade( self:getLevel() ) then
            ret = true
            break
        end
    end
    return ret
end

-- 判定技能是否可以升级
function UserData:isSkillCanUpgrade(skillId)
    if self:getSkillPoint() <= 0 then
        return false
    end

    local skill = self.skills[skillId]
    if skill then
        return skill:canUpgrade()
    end
    return false
end

------------------------- 天赋 -----------------------
-- 从配置初始化本职业所有的talent
function UserData:_initAllTalents()
    local talentsSpecDict = {}
    local talentDict = {}
    local confsDict = GD:getTalentConfsByClass(UD:getClass())
    for specId,confs in pairs(confsDict) do
        local talents = {}
        for i,conf in ipairs(confs) do
            -- 天赋对应的技能都只有一个
            local skillConfs = GD:querySkillsByTeam(conf.skillteam)
            local talentId = tonumber(skillConfs[1].ID)
            local talent = Talent.new()
            talent:read({uid=talentId})
            talents[#talents + 1] = talent
            talentDict[talentId] = talent
        end
        talentsSpecDict[specId] = talents
    end

    self._talentsSpecDict = talentsSpecDict
    self._talentDict = talentDict

    -- dump(talentsSpecDict, "UD.talentsSpecDict")
    -- dump(talentDict, "UD.talentDict")
end

function UserData:getSpecTalents(specId)
    specId = specId or self:getCurSpecTypeId()
    return self._talentsSpecDict[specId]
end

--获取所有的天赋 (has map)
function UserData:getAllTalents()
    return self._talentDict
end

function UserData:getTalent(id)
    return self._talentDict[id]
end

--获得已学习的天赋
function UserData:getTalents()
    return self.talents
end

function UserData:hasTalent(id)
    return self.talents[id]~=nil
end

function UserData:getTalentPoint()
    return self._coinWallets[86] or 0
end


------------------------- 符文 -----------------------
-- 初始化符文相关数据
-- 针对自己职业的3个专精、8个槽位解析处符文列表
function UserData:_initRuneData()
    local runesSpecDict = {}
    local runeDict = {}
    local specTypes = self._specTypes
    for _,specType in ipairs( specTypes ) do
        local specId = specType.id
        if nil == runesSpecDict[ specId ] then
            runesSpecDict[ specId ] = {}
        end
        for i = 1, Constant.Rune_EquipPlace_Num do
            if nil == runesSpecDict[ specId ][ i ] then
                runesSpecDict[ specId ][ i ] = {}
            end
            local runConfs = GD:queryRuneByClassAndEquipPlace( specId, i )
            for _, conf in ipairs( runConfs ) do
                -- 没有技能的符文不要
                if conf.team ~= "0" then
                    local rune = Rune.new( { id = tonumber( conf.ID ) } )
                    runeDict[rune:getId()] = rune
                    table.insert( runesSpecDict[ specId ][ i ], rune )
                end
            end

            self._runePlaceDirtyDict[i] = true
        end
    end

    self._runeDataDirty = true
    self._runesSpecDict = runesSpecDict
    self._runeDict = runeDict

    -- dump(self._runesSpecDict, "UD._runesSpecDict")
end

function UserData:_setRunePlaceDirtyFlag(place)
    self._runePlaceDirtyDict[place] = true
end

function UserData:getRune(id)
    return self._runeDict[id]
end

function UserData:getActiveRuneByTeam(team)
    for k,rune in pairs(self.runes) do
        if rune:isEquiped() and rune:getSkillTeam() == team then
            return rune
        end
    end
end

-- 符文排序 装备》获得〉id升序
local function runeSortFunc(a, b)
    local equiped_a = a:isEquiped()
    local equiped_b = b:isEquiped()
    if equiped_a == equiped_b then
        local isGot_a = a:isGot()
        local isGot_b = b:isGot()
        if isGot_a == isGot_b then
            return a:getId() < b:getId()
        else
            return isGot_a
        end
    else
        return equiped_a
    end
end

-- specId 专精id
-- isSort 是否排序
function UserData:getSpecRunesList(specId, isSort)
    specId = specId or self.player.skillChooseID
    local runesList = self._runesSpecDict[specId]
    for i,runes in ipairs(runesList) do
        if isSort and self._runePlaceDirtyDict[i] then
            self._runePlaceDirtyDict[i] = false
            table.sort(runes, runeSortFunc)
        end
    end
    return runesList
end

-- 返回某个符文是否获得?
function UserData:isRuneGot( runeId )
    runeId = tonumber( runeId or 0 )
    return self.runes[runeId] ~= nil
end

-- 当前专精的符文是否可操作的
-- pos 某位置的符文是否可以操作
function UserData:isSpecRunesHasOp(specId, pos)
    local runeList = self:getSpecRunesList(specId)
    local hasOp = false
    if pos then
        local runes = runeList[pos]
        local isGot, isEquiped = false, false
        for j,rune in ipairs(runes) do
            if rune:isGot() then
                isGot = true
                isEquiped = isEquiped or rune:isEquiped()
            end
        end
        hasOp = (isGot and not isEquiped)

    else
        for i,runes in ipairs(runeList) do
            local isGot, isEquiped = false, false
            for j,rune in ipairs(runes) do
                if rune:isGot() then
                    isGot = true
                    isEquiped = isEquiped or rune:isEquiped()
                end
            end

            -- 可操作：获得了符文但是没有装备
            hasOp = (isGot and not isEquiped)
            if hasOp then
                break
            end
        end
    end

    return hasOp
end

-- 返回某个符文是否激活（使用）?
function UserData:isRuneActived( runeId )
    runeId = tonumber( runeId or 0 )
    local rune = self.runes[ runeId ]
    if rune then
        return rune:isEquiped()
    end
    return false
end

-------------------新获得符文相关--------------------
function UserData:clearNewGetRunes()
    for k,rune in pairs(self.runes) do
        rune:setIsNewGet(false)
    end
end
function UserData:removeNewGetRune(runeId)
    local rune = self.runes[runeId]
    if rune and rune.isNew then
        rune:setIsNewGet(false)
        UD.redPoint:checkStateByKey(RedPointConstant.Skill_Rune)
    end
end
--是否是新获得符文
function UserData:isNewGetRune(runeId)
    local rune = self.runes[runeId]
    if rune then
        return rune.isNew
    end
    return false
end

-- 只考虑当前激活专精的符文
function UserData:isNewGetRunesExist()
    local curSpecId = self.player.skillChooseID
    for k,rune in pairs(self.runes) do
        if rune.isNew and rune:getSpecId() == curSpecId then
            return true
        end
    end
    return false
end
--------------------------------------------------

return UserData
